package executor

import (
	"sync"
	"time"
)

type TimerTask struct {
	Ctx      interface{}
	Handler  func(ctx interface{})
	Interval int64 // 单位秒
	expire   int64
}

type TimerExecutor struct {
	sync.Mutex
	tasks   []*TimerTask
	closeCh chan struct{}
}

func (e *TimerExecutor) exec() {
	e.Lock()
	defer e.Unlock()

	for _, v := range e.tasks {
		if time.Now().Unix() >= v.expire {
			v.Handler(v.Ctx)
			v.expire = time.Now().Unix() + v.Interval
		}
	}
}

func (e *TimerExecutor) loop() {
	ticker := time.NewTicker(time.Second)
	defer ticker.Stop()

	for {
		select {
		case <-e.closeCh:
			return
		case <-ticker.C:
			break
		}

		e.exec()
	}
}

func (e *TimerExecutor) AddTask(t *TimerTask) {
	e.Lock()
	defer e.Unlock()
	t.expire = time.Now().Unix() + t.Interval
	e.tasks = append(e.tasks, t)
}

func (e *TimerExecutor) DelTask(t *TimerTask) {
	e.Lock()
	defer e.Unlock()

	tmp := e.tasks[:0]
	for _, v := range e.tasks {
		if v != t {
			tmp = append(tmp, v)
		}
	}

	e.tasks = tmp
}

func (e *TimerExecutor) Close() {
	e.closeCh <- struct{}{}
}

func NewTimerExecutor() *TimerExecutor {
	e := &TimerExecutor{
		tasks:   make([]*TimerTask, 0),
		closeCh: make(chan struct{}, 1),
	}

	go e.loop()

	return e
}
